// Geometric Tools, LLC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
//
// File Version: 5.0.0 (2010/01/01)

#include "SquirrelAdven.h"
#include <math.h>
#include <sstream>
#include "fmod.hpp"
#include "fmod_errors.h"
#ifdef OS_WIN
#include "windows.h"
#include <conio.h>
#else
#include "wincompat.h"
#endif
#include <stdio.h>

#define PI 3.1415926

WM5_WINDOW_APPLICATION(SquirrelAdven);

FMOD::System	*sys;
FMOD::Sound		*sound;
FMOD_RESULT		result;
bool logGivenN = false;
bool logGivenD = false;

void ERRCHECK(FMOD_RESULT result)
{
	if (result != FMOD_OK)
	{
		printf("FMOD error! (%d) %s\n", result, FMOD_ErrorString(result));
		exit(-1);
	}
}
//----------------------------------------------------------------------------
SquirrelAdven::SquirrelAdven ()
	:
WindowApplication3("SquirrelAdven", 0, 0, 1000, 600,
	Float4(1.0f, 1.0f, 1.0f, 1.0f)),
	mTextColor(1.0f, 1.0f, 1.0f, 1.0f)
{
	// multiplayer
	numPlayer = 2;
	selfPlayerID = 0;

	// parameters

	items = new0 Node();
	moveSpeed = 1.5;
	rotSpeed = 0.005;

	mPlayerPos_x=0.785f;
	mPlayerPos_y=0.945f;

	mPickMessage[0] = 0;

	dialogMode = false;
	option = -1;

	gamemap = new0 Node();

	onLeftKeyDown = false;
	onRightKeyDown = false;
	onUpKeyDown = false;
	onDownKeyDown = false;
	showMap=false;
	gameEnd = false;
}
//----------------------------------------------------------------------------
bool SquirrelAdven::OnInitialize ()
{
	if (!WindowApplication3::OnInitialize())
	{
		return false;
	}

	// Set up the camera.
	mCamera->SetFrustum(30.0f, GetAspectRatio(), 1.0f, 2000.0f);
	APoint camPosition;
	AVector camDVector;

	// horizontal view

	
	camPosition = APoint(-180.0, -192.0, 75.0);
	//camPosition = APoint(-180.0f, -193.5f, 87.0f);
	camDVector = AVector(0.0f, 0.0f, -1.0f);
	AVector camUVector(0.0f, 1.0f, 0.0f); 
	 
	// top down view

	/*
	camPosition = APoint(0.0f, 990.0f, 0.0f);
	camDVector = AVector(0.0f, -1.0f, 0.0f);
	AVector camUVector(0.0f, 0.0f, 1.0f);
	*/


	AVector camRVector = camDVector.Cross(camUVector);
	mCamera->SetFrame(camPosition, camDVector, camUVector, camRVector);

	CreateScene();

	// Initial update of objects.
	mScene->Update();

	// Initial culling of scene.
	mCuller.SetCamera(mCamera);
	mCuller.ComputeVisibleSet(mScene);

	InitializeCameraMotion(moveSpeed, rotSpeed);
	InitializeObjectMotion(mScene);




	//Andrew - this is how I did debugging in my other program, since printf's didn't work.
	//it writes to a file, does not append
	outFile.open("OUTPUT.TXT", ios::out);
	outFile << "hello from OnInit()"<< endl;
	isTyping=false;
	chatCounter=0;
	chatMessage=(char *)malloc(256);
	ServerMessage=(char *)malloc(256);
	Intro=1;
#if defined (MULTIPLAYERMODE)
#ifdef OS_WIN	
	//pass the object to the thread
	HANDLE thread = CreateThread (NULL, 0, (unsigned long (__stdcall *)(void *))this->ThreadFunc, 
		(void *)this, 0, NULL);

	//mac
#else
	pthread_t t;
	//pthread_create(&t, NULL, &C::hello_helper, &c);
	pthread_create(&t,NULL,&SquirrelAdven::listen_helper,this);
#endif
	network.sendMessage("1 startingup\n");
#endif	


	return true;
}
//----------------------------------------------------------------------------
void SquirrelAdven::OnTerminate ()
{
	mScene = 0;
	mCuller = 0;

	result = sound->release();
	ERRCHECK(result);
	result = sys->close();
	ERRCHECK(result);
	result = sys->release();
	ERRCHECK(result);

	WindowApplication3::OnTerminate();
}
//----------------------------------------------------------------------------
void SquirrelAdven::OnIdle ()
{
	MeasureTime();

	if (MoveCamera())
	{
		mCuller.ComputeVisibleSet(mScene);
	}

	if (MoveObject())
	{
		mScene->Update();
		mCuller.ComputeVisibleSet(mScene);
	}

	UpdateSquirrelAdven();

	if (mRenderer->PreDraw())
	{
		mRenderer->ClearBuffers();

		mRenderer->Draw(mCuller.GetVisibleSet());
		DrawFrameRate(GetWidth()-100, GetHeight()-8, mTextColor);

		// Draw Player Inventory and Points
		Node * curPlayerNode = playerNodes[selfPlayerID];
		Player * curPlayer = playerList->getPlayerByID(selfPlayerID);

		mInventoryMessage = curPlayer->printInventory();
		mRenderer->Draw(8, GetHeight()-8, mTextColor, mInventoryMessage);

		int numPoints = curPlayer->totalPoints();
		std::stringstream ss;
		ss << "|\tPoints:\t" << numPoints;
		mRenderer->Draw(8, GetHeight()-24, mTextColor, ss.str());

		//	Display NPC interaction
		mRenderer->Draw(8, 60, mTextColor, mNPCMessage_npc);
		mRenderer->Draw(8, 80, mTextColor, mNPCMessage_option);
		mRenderer->Draw(8, 100, mTextColor, mNPCMessage_player);

		if (mPickMessage[0])
		{
			mRenderer->Draw(GetWidth()/2, 16, mTextColor, mPickMessage);
		}
		//added this if statement for mPicker
		if (isTyping==true && chatCounter>0)
		{
			//outFile<<"using typing: "<<chatMessage;
			mRenderer->Draw(8, 16, mTextColor, chatMessage);
		}


		sprintf(ServerMessageToScreen, "Chat:%s",ServerMessage);
		mRenderer->Draw(8, 30, mTextColor, ServerMessageToScreen);
		// Draw the foreground polygon last since it has transparency.
		mRenderer->SetCamera(mScreenCamera);

		if(Intro==1){
			mRenderer->Draw(mIntro);
		}
		else if(Intro==2){
			mRenderer->Draw(mIntro2);
		}
		else if(Intro==3){
			mRenderer->Draw(mIntro3);
		}
		else if (Intro==4){
			mRenderer->Draw(mIntro4);
		}
		else if(Intro==5){
			mRenderer->Draw(mIntro5);
		}
		else if(showMap==true && gameEnd==false){
			mRenderer->Draw(mForePoly);
			mRenderer->Draw(mForePlayer);
		}
		
		//end
		if (gameEnd == true) {
			mRenderer->Draw(mEnd);
		}
		
		mRenderer->SetCamera(mCamera);
		mRenderer->PostDraw();
		mRenderer->DisplayColorBuffer();
	}
	mScene->Update();
	UpdateFrameCount();
}
void SquirrelAdven::startBackgroundMusic(){
	FMOD::Channel	*channel = 0;
	unsigned int	version;


	// Global Settings

	result = FMOD::System_Create(&sys);
	ERRCHECK(result);

	result = sys->getVersion(&version);
	ERRCHECK(result);

	if (version < FMOD_VERSION)
	{
		printf("Error!  You are using an old version of FMOD %08x.  This program requires %08x\n", version, FMOD_VERSION);
		getch();
		//        return 0;
	}

	result = sys->init(1, FMOD_INIT_NORMAL, 0);
	ERRCHECK(result);

	result = sys->createSound("forest_sound.mp3", (FMOD_MODE)(FMOD_SOFTWARE | FMOD_2D | FMOD_CREATESTREAM), 0, &sound);
	ERRCHECK(result);

	// Play Sound
	result = sys->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);
	ERRCHECK(result);
	sound->setMode(FMOD_LOOP_NORMAL);

	sys->update();

	if (channel)
	{
		unsigned int ms;
		unsigned int lenms;
		bool         playing;
		bool         paused;

		channel->isPlaying(&playing);
		if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE))
		{
			ERRCHECK(result);
		}

		result = channel->getPaused(&paused);
		if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE))
		{
			ERRCHECK(result);
		}

		result = channel->getPosition(&ms, FMOD_TIMEUNIT_MS);
		if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE))
		{
			ERRCHECK(result);
		}

		result = sound->getLength(&lenms, FMOD_TIMEUNIT_MS);
		if ((result != FMOD_OK) && (result != FMOD_ERR_INVALID_HANDLE))
		{
			ERRCHECK(result);
		}
	}

	Sleep(10);
}
//----------------------------------------------------------------------------
bool SquirrelAdven::OnKeyDown (unsigned char key, int x, int y)
{
	if (WindowApplication3::OnKeyDown(key, x, y))
	{
		return true;
	}

	if(isTyping==true){
		chatMessage[chatCounter]=key;
		chatCounter++;
		return true;
	}
	else {
		if (dialogMode == true) {
			Player * curPlayer = playerList->getPlayerByID(selfPlayerID);
			talkWithNPC(curPlayer);
			if (!(key == 'a' || key == 'd' || key == 'w' || key == 's')) {
				option = (key - '0') % 2 ;
				if (option == 0) {
					option = 2;
				}
				std::ostringstream ss; 
				ss << option; 
				mNPCMessage_player = "You chose: " + ss.str();
			}
			return true;
		}
	}
	if (key == 'a')
	{
		onLeftKeyDown = true;
		return true;
	}
	if (key == 'd')
	{
		onRightKeyDown = true;
		return true;
	}
	if (key == 'w')
	{
		onUpKeyDown = true;
		return true;
	}
	if (key == 's')
	{
		onDownKeyDown = true;
		return true;
	}

	return false;
}

bool SquirrelAdven::OnKeyUp (unsigned char key, int x, int y) {
	if (key == 'a')
	{
		onLeftKeyDown = false;
		return true;
	}
	if (key == 'd')
	{
		onRightKeyDown = false;
		return true;
	}
	if (key == 'w')
	{
		onUpKeyDown = false;
		return true;
	}
	if (key == 's')
	{
		onDownKeyDown = false;
		return true;
	}

	return false;
}

//----------------------------------------------------------------------------
bool SquirrelAdven::OnSpecialKeyDown (int key, int, int)
{
	Player * curPlayer = playerList->getPlayerByID(selfPlayerID);

	if (mCameraMoveable)
	{
		if (dialogMode == true) {
			if (key == KEY_RETURN || key == KEY_ALT) {
				DialogTree * tree = curTalkingNPC->getDialogTree();
				if (tree != NULL && curDialogNode->getDialogID() < tree->getLastDialogID()) {
					if (curDialogNode->getChildrenCount() > 0) {
						curDialogNode = tree->getNextDialogNode(curDialogNode, option);
						curPlayer->addPoints(curDialogNode->getDialogPoints());
					}
					// no next dialog node
					else {
						dialogMode = false;
					}
				}
				// no more dialog node
				else{
					dialogMode = false;
				}
			}
			// exit dialog mode
			else if(key == KEY_BACKSPACE || key == KEY_DELETE) {
				dialogMode = false;
			}
			talkWithNPC(curPlayer);
			return true;
		}

		mNPCMessage_npc = "";
		mNPCMessage_option = "";
		mNPCMessage_player = "";


		if (key == KEY_LEFT_ARROW)
		{
			onLeftKeyDown = true;
			return true;
		}
		if (key == KEY_RIGHT_ARROW)
		{
			onRightKeyDown = true;
			return true;
		}
		if (key == KEY_UP_ARROW)
		{
			onUpKeyDown = true;
			return true;
		}
		if (key == KEY_DOWN_ARROW)
		{
			onDownKeyDown = true;
			return true;
		}

		if (key == KEY_CONTROL) {
			outFile <<"user pressed control for chat"<<endl;
			//how to detect if the user is typing
			if(isTyping==false){
				isTyping=true;
			}
			else{
				isTyping=false;

#if defined (MULTIPLAYERMODE)
				//memset(ServerMessage,0,strlen(ServerMessage));
				//chatMessage[chatCounter+2]='\0';//add end of word
				//chatMessage[chatCounter+1]='\0';
				string temp(chatMessage);
				temp="0 "+temp;
				temp.copy(chatMessage,temp.length(),0);
				chatMessage[chatCounter+2]='\0';
				//string temptwo(chatMessage);
				//chat message is now "0 chatmessage"....could sprintf work?


				/*
				mystr.copy(buf,mystr.length());
				buf[mystr.length()]='\0';
				buf[mystr.length()+1]='\n';
				*/
				outFile<<"Sending:"<<chatMessage<<endl;

				network.sendMessage(chatMessage);
				memset(chatMessage,0,strlen(chatMessage));
				chatCounter=0;
				//chatMessage=(char *)malloc(256);//i have to remalloc it again for whatever reason to see it....
				/*
				outFile <<"Server Response:"<<ServerMessage<<endl;
				std::cout <<"Server Response:"<<ServerMessage<<endl;*/
#endif

				//chatMessage=(char *)malloc(256);
				//ServerMessage=(char *)malloc(256);
			}
			//append all letters typed until the message is done, then send
			return true;

		}

	}

	return false;
}

bool SquirrelAdven::OnSpecialKeyUp (int key, int x, int y) {
	if (key == KEY_LEFT_ARROW)
	{
		onLeftKeyDown = false;
		return true;
	}
	if (key == KEY_RIGHT_ARROW)
	{
		onRightKeyDown = false;
		return true;
	}
	if (key == KEY_UP_ARROW)
	{
		onUpKeyDown = false;
		return true;
	}
	if (key == KEY_DOWN_ARROW)
	{
		onDownKeyDown = false;
		return true;
	}

	return false;
}
//----------------------------------------------------------------------------
bool SquirrelAdven::OnMouseClick (int button, int state, int x, int y, unsigned int)
{
	if (state != MOUSE_DOWN && state != MOUSE_LEFT_BUTTON)
	{
		return false;
	}
	if(state == MOUSE_DOWN){

		if(Intro==1||Intro==2||Intro==3||Intro==4||Intro==5){
			Intro++;
		}
		if(Intro==6){
			Intro=false;
			startBackgroundMusic();
		}

	}
	// Do a picking operation
	APoint pos;
	AVector dir;
	//	int itemID;
	if (mRenderer->GetPickRay(x, GetHeight() - 1 - y, pos, dir))
	{
		mPicker.Execute(mScene, pos, dir, 0.0f, Mathf::MAX_REAL);
		if (mPicker.Records.size() > 0)
		{
			// Display selected object's name
			const PickRecord& record = mPicker.GetClosestNonnegative();
			const Spatial* object = record.Intersected;
			sprintf(mPickMessage, "%s", object->GetName().c_str());
			// if object within certain distance
			{
				//		/*const*/ Spatial* object = record.Intersected;
				outFile<<"object title: "<<object->GetName().c_str()<<'\n';
				std::cout<<"object title: "<<object->GetName().c_str()<<'\n';
				/*			if (strcmp(object->GetName().c_str(),"stick")==0 || strcmp(object->GetName().c_str(),"acorn")==0)
				{
				Items* item = itemList->getItemByTitle(object->GetName().c_str());
				//		Items* oldItem = curPlayer->addToInventory(item);
				//		if (oldItem != NULL) {
				//	std::cout<< "oldItem not NULL\n";
				TriMesh * curMesh = oldItem->getItemMesh();
				curMesh->SetName(oldItem->getItemTitle());
				//float* trans = item.getTranslate()
				//	std::cout<<"item locationx: " << item->getTranslateX() << "\n";
				//	std::cout<<"item locationy: " << item->getTranslateY() << "\n";
				//	std::cout<<"item locationz: " << item->getTranslateZ() << "\n";
				curMesh->LocalTransform.SetTranslate(APoint(item->getTranslateX(), item->getTranslateY(), item->getTranslateZ()));
				// place at location of item just picked up ... curMesh->LocalTransform.SetTranslate(APoint());
				// mScene->AttachChild(curMesh);
				// items->AttachChild(curMesh);
				}
				TriMesh *invItem = item->getItemMesh();
				invItem->LocalTransform.SetTranslate(APoint(-15.0, -300.0, -50.0));				//	itemID = item->getItemID();
				mScene->Update();
				*/

				std::cout<<"ObjectTitleAgain: " << object->GetName().c_str() << "\n";
				//				sprintf(mPickMessage, "%s", object->GetName().c_str());
				//			}
			}
		}
		else
		{
			mPickMessage[0] = 0;
		}
	}
	return true;
}
//----------------------------------------------------------------------------
void SquirrelAdven::CreateLights ()
{
	mDLightRoot = new0 Node();
	mScene->AttachChild(mDLightRoot);

	// light 1
	mDLight1 = new0 Light(Light::LT_DIRECTIONAL);
	mDLight1->Ambient = Float4(1.0f, 1.0f, 1.0f, 1.0f);
	mDLight1->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f);
	mDLight1->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f);

	mDLight1->DVector = AVector(-0.25f, -0.25f, -1.0f);
	mDLight1->DVector.Normalize();

	LightNode* lightNode1 = new0 LightNode(mDLight1);
	mDLightRoot->AttachChild(lightNode1);

	// light 2
	mDLight2 = new0 Light(Light::LT_DIRECTIONAL);
	mDLight2->Ambient = Float4(1.0f, 1.0f, 1.0f, 1.0f);
	mDLight2->Diffuse = Float4(1.0f, 1.0f, 1.0f, 1.0f);
	mDLight2->Specular = Float4(1.0f, 1.0f, 1.0f, 1.0f);

	LightNode* lightNode2 = new0 LightNode(mDLight2);
	mDLightRoot->AttachChild(lightNode2);

	mDLightRoot->Update();
}

//----------------------------------------------------------------------------
void SquirrelAdven::CreateScene ()
{

	// The screen camera is designed to map (x,y,z) in [0,1]^3 to (x',y,'z')
	// in [-1,1]^2 x [0,1].
	mScreenCamera = new0 Camera(false);
	mScreenCamera->SetFrustum(0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f);
	mScreenCamera->SetFrame(APoint::ORIGIN, AVector::UNIT_Z, AVector::UNIT_Y,
		AVector::UNIT_X);
	CreateHUD();
	CreateIntroHUD();
	mScene = new0 Node();


	CreateRoom();
	CreateMap();
	CreateNPC();
	CreatePlayer();
	CreateItem();


	/*
	// Set up the collision system.  Record0 handles the collision response.
	// Record1 is not given a callback so that 'double processing' of the
	// events does not occur.
	CTree* tree0 = new0 CTree(gameMap->getMapMesh(), 1, false);
	CRecord* record0 = new0 CRecord(tree0, 0, Response, this);
	CTree* tree1 = new0 CTree(curPlayer->getPlayerMesh(), 1, false);
	CRecord* record1 = new0 CRecord(tree1, 0, 0, 0);
	mGroup = new0 CGroup();
	mGroup->Add(record0);
	mGroup->Add(record1);

	mGroup->TestIntersection();
	*/

}


void SquirrelAdven::CreateRoom() {
	Node* room = new0 Node();
	mScene->AttachChild(room);

	// Index buffer shared by the room walls.
	IndexBuffer* ibuffer = new0 IndexBuffer(6, sizeof(int));
	int* indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 3;
	indices[3] = 0;  indices[4] = 3;  indices[5] = 2;

	// The vertex format shared by the room walls.
	VertexFormat* vformat = VertexFormat::Create(2,
		VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
		VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
	int vstride = vformat->GetStride();
	VertexBufferAccessor vba;

	// The texture effect shared by the room walls.
	Texture2DEffect* effect = new0 Texture2DEffect(Shader::SF_LINEAR);

	VertexBuffer* vbuffer;
	TriMesh* wall;
	std::string textureName;

	// +x wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(1) = Float3(+1.0f, -1.0f, +1.0f);
	vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, -1.0f);
	vba.Position<Float3>(3) = Float3(+1.0f, +1.0f, +1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("SkyDome.wmtf");
	Texture2D* xpTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(xpTexture));

	// -x wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, +1.0f);
	vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(2) = Float3(-1.0f, +1.0f, +1.0f);
	vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, -1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("SkyDome.wmtf");
	Texture2D* xmTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(xmTexture));

	// +y wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(+1.0f, +1.0f, +1.0f);
	vba.Position<Float3>(1) = Float3(-1.0f, +1.0f, +1.0f);
	vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, -1.0f);
	vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, -1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("SkyDome.wmtf");
	Texture2D* ypTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(ypTexture));

	// -y wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(2) = Float3(+1.0f, -1.0f, +1.0f);
	vba.Position<Float3>(3) = Float3(-1.0f, -1.0f, +1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("Floor.wmtf");
	Texture2D* ymTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(ymTexture));

	// +z wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(+1.0f, -1.0f, +1.0f);
	vba.Position<Float3>(1) = Float3(-1.0f, -1.0f, +1.0f);
	vba.Position<Float3>(2) = Float3(+1.0f, +1.0f, +1.0f);
	vba.Position<Float3>(3) = Float3(-1.0f, +1.0f, +1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("SkyDome.wmtf");
	Texture2D* zpTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(zpTexture));

	// -z wall
	vbuffer = new0 VertexBuffer(4, vstride);
	vba.ApplyTo(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(-1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(1) = Float3(+1.0f, -1.0f, -1.0f);
	vba.Position<Float3>(2) = Float3(-1.0f, +1.0f, -1.0f);
	vba.Position<Float3>(3) = Float3(+1.0f, +1.0f, -1.0f);
	vba.TCoord<Float2>(0, 0) = Float2(0.0f, 0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(0.0f, 1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	wall = new0 TriMesh(vformat, vbuffer, ibuffer);
	room->AttachChild(wall);
	textureName = Environment::GetPathR("SkyDome.wmtf");
	Texture2D* zmTexture = Texture2D::LoadWMTF(textureName);
	wall->SetEffectInstance(effect->CreateInstance(zmTexture));

	room->LocalTransform.SetScale(APoint(1000.0, 200.0, 1000.0));

}
void SquirrelAdven::CreateMap() {
	mScene->AttachChild(gamemap);

	gameMap = new Map("map.obj", "forest.wmtf");
	TriMesh * mapMesh = gameMap->getMapMesh();
	mapMesh->LocalTransform.SetScale(APoint(30.0, 50.0, 30.0));
	mapMesh->LocalTransform.SetRotate(HMatrix(AVector(0.0, 1.0, 0.0), PI/2));
	mapMesh->LocalTransform.SetTranslate(APoint(0.0, -200.0, -50.0));
	gamemap->AttachChild(mapMesh);

	cout << "map x: " << gameMap->getOriginalLengthX() << "\n";
	cout << "map y: " << gameMap->getOriginalLengthY() << "\n";
	cout << "map z: " << gameMap->getOriginalLengthZ() << "\n";
}

void SquirrelAdven::CreateNPC() {
	Node* npcs = new0 Node();
	mScene->AttachChild(npcs);

	npcList = new NPCList("NPCInfo.txt");
	int i;

	for (i = 0 ; i < npcList->getNPCCount(); i++) {
		NPC * cur = npcList->getNPCByID(i);
		TriMesh * curMesh = cur->getCharacterMesh();
		curMesh->SetName(cur->getCharacterName());

		APoint scale_p (cur->getOriginalScaleX(), cur->getOriginalScaleY(), cur->getOriginalScaleZ());
		curMesh->LocalTransform.SetScale(scale_p);
		cur->modifyRadius(scale_p);

		APoint translate_p (cur->getOriginalTranslateX(), cur->getOriginalTranslateY(), cur->getOriginalTranslateZ());
		curMesh->LocalTransform.SetTranslate(translate_p);
		cur->modifyCenterPoint(translate_p);		


		//curMesh->LocalTransform.SetRotate(HMatrix(AVector(0.0, 1.0, 0.0), PI));

		npcs->AttachChild(curMesh);
	}
}

void SquirrelAdven::CreateItem() {
	//	Node* items = new0 Node();
	mScene->AttachChild(items);

	itemList = new ItemList("ItemInfo.txt");
	int i;

	cout << itemList->getItemCount() << "\n";
	for (i = 0; i < itemList->getItemCount(); i++) {
		Items * cur = itemList->getItemByID(i);
		TriMesh * curMesh = cur->getItemMesh();
		curMesh->SetName(cur->getItemTitle());

		APoint scale_p (0.3, 0.3, 0.3);
		curMesh->LocalTransform.SetScale(scale_p);
		cur->modifyRadius(scale_p);

		APoint translate_p (cur->getTranslateX(), cur->getTranslateY(), cur->getTranslateZ());
		curMesh->LocalTransform.SetTranslate(translate_p);
		cur->modifyCenterPoint(translate_p);

		//curMesh->LocalTransform.SetRotate(HMatrix(AVector(0.0, 0.0, 1.0),  PI/ 12));

		items->AttachChild(curMesh);
	}
}

void SquirrelAdven::CreatePlayer() {
	playerList = new PlayerList(numPlayer);
	int i;
	for (i = 0; i < numPlayer; i++) {
		Player * cur = playerList->getPlayerByID(i);
		TriMesh * curMesh = cur->getPlayerMesh();
		playerNodes[i] = new0 Node();
		playerNodes[i]->AttachChild(curMesh);

		APoint scale_p (2.0, 2.0, 2.0);
		playerNodes[i]->LocalTransform.SetScale(scale_p);
		cur->modifyRadius(scale_p);

		APoint translate_p(-180.0, -196.0, 75.0);
		playerNodes[i]->LocalTransform.SetTranslate(translate_p);
		cur->modifyCenterPoint(translate_p);

		playerNodes[i]->LocalTransform.SetRotate(HMatrix(AVector(0.0, 1.0, 0.0),  -11 * PI/ 12));

		mScene->AttachChild(playerNodes[i]);
	}
}


//----------------------------------------------------------------------------
void SquirrelAdven::UpdateSquirrelAdven ()
{
	if (onLeftKeyDown == true)
	{
		leftKeyDown(selfPlayerID);
		//notify other player
#if defined (MULTIPLAYERMODE)
		network.sendMessage("3 rotateleft\n");	
#endif
	}
	if (onRightKeyDown == true)
	{
		rightKeyDown(selfPlayerID);
		//notify other player
#if defined (MULTIPLAYERMODE)
		network.sendMessage("3 rotateright\n");	
#endif
	}
	if (onUpKeyDown == true)
	{
		upKeyDown();
		//notify other player
#if defined (MULTIPLAYERMODE)
		network.sendMessage("2 forward\n");	
#endif
	}
	if (onDownKeyDown == true)
	{
		downKeyDown();
		//notify other player
#if defined (MULTIPLAYERMODE)
		network.sendMessage("2 backward\n");	
#endif
	}

	mScene->Update();
	mCuller.ComputeVisibleSet(mScene);
}
//----------------------------------------------------------------------------
void SquirrelAdven::UpdateHUD ()
{
	//outFile << "From UpdateHUD(), mPlayerPos_x:"<<mPlayerPos_x<< endl;
	//outFile << "HEY"<< endl;
	VertexFormat* vformat = VertexFormat::Create(2,
		VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
		VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
	int vstride = vformat->GetStride();
	VertexBuffer* vbuffer = new0 VertexBuffer(5, vstride);
	VertexBufferAccessor vba(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(mPlayerPos_x,  mPlayerPos_y,  0.0f);
	vba.Position<Float3>(1) = Float3(mPlayerPos_x+0.01f,  mPlayerPos_y,  0.0f);
	vba.Position<Float3>(2) = Float3(mPlayerPos_x+0.01f, mPlayerPos_y+0.01f,  0.0f);
	vba.Position<Float3>(3) = Float3(mPlayerPos_x+0.01f,  mPlayerPos_y+0.01f, 0.0f);
	vba.Position<Float3>(4) = Float3(mPlayerPos_x,  mPlayerPos_y+0.01f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);



	IndexBuffer*ibuffer = new0 IndexBuffer(9, sizeof(int));
	int* indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mForePlayer = new0 TriMesh(vformat, vbuffer, ibuffer);
	std::string path = Environment::GetPathR("green.wmtf");
	Texture2DEffect* foreEffect = new0 Texture2DEffect(Shader::SF_LINEAR);
	Texture2D* texture = Texture2D::LoadWMTF(path);
	mForePlayer->SetEffectInstance(foreEffect->CreateInstance(texture));

	// Make the foreground semitransparent.
	foreEffect->GetAlphaState(0, 0)->BlendEnabled = true;
}
//----------------------------------------------------------------------------

void SquirrelAdven::CreateIntroHUD(){
	// A portion of the foreground is a textured screen polygon (z = 0).
	VertexFormat* vformat = VertexFormat::Create(2,
		VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
		VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
	int vstride = vformat->GetStride();
	VertexBuffer* vbuffer = new0 VertexBuffer(5, vstride);
	VertexBufferAccessor vba(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(0.0f,  0.0f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.0f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);



	IndexBuffer*ibuffer = new0 IndexBuffer(9, sizeof(int));
	int* indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mIntro = new0 TriMesh(vformat, vbuffer, ibuffer);
	std::string path = Environment::GetPathR("openingscene-1.wmtf");
	Texture2DEffect* foreEffect = new0 Texture2DEffect(Shader::SF_LINEAR);
	Texture2D* texture = Texture2D::LoadWMTF(path);
	mIntro->SetEffectInstance(foreEffect->CreateInstance(texture));

	// Make the foreground semitransparent.
	foreEffect->GetAlphaState(0, 0)->BlendEnabled = true;


	//make part 2

	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);

	vba.Position<Float3>(0) = Float3(0.0f,  0.0f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.0f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mIntro2 = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("openingscene-2.wmtf");
	Texture2DEffect* introEffect2 = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mIntro2->SetEffectInstance(introEffect2->CreateInstance(texture));

	// Make the foreground semitransparent.
	//mIntro2->GetAlphaState(0, 0)->BlendEnabled = true;

	//make part3
	//make part 2

	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);

	vba.Position<Float3>(0) = Float3(0.0f,  0.0f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.0f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mIntro3 = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("openingscene-3.wmtf");
	Texture2DEffect* introEffect3 = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mIntro3->SetEffectInstance(introEffect3->CreateInstance(texture));

	// Make the foreground semitransparent.
	//mIntro2->GetAlphaState(0, 0)->BlendEnabled = true;


	//make part 4

	//make part 2

	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);

	vba.Position<Float3>(0) = Float3(0.0f,  0.0f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.0f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mIntro4 = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("openingscene-4.wmtf");
	Texture2DEffect* introEffect4 = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mIntro4->SetEffectInstance(introEffect4->CreateInstance(texture));

	// Make the foreground semitransparent.
	//mIntro2->GetAlphaState(0, 0)->BlendEnabled = true;

	//make part 5, instructions
	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);

	vba.Position<Float3>(0) = Float3(0.0f,  0.0f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.0f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mIntro5 = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("instructions.wmtf");
	Texture2DEffect* introEffect5 = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mIntro5->SetEffectInstance(introEffect5->CreateInstance(texture));
	//make part end
	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);

	vba.Position<Float3>(0) = Float3(0.0f,  0.1f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.1f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.0f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mEnd = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("EndScene.wmtf");
	Texture2DEffect* endEffect = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mEnd->SetEffectInstance(endEffect->CreateInstance(texture));
}

//----------------------------------------------------------------------------

void SquirrelAdven::CreateHUD(){
	// A portion of the foreground is a textured screen polygon (z = 0).
	VertexFormat* vformat = VertexFormat::Create(2,
		VertexFormat::AU_POSITION, VertexFormat::AT_FLOAT3, 0,
		VertexFormat::AU_TEXCOORD, VertexFormat::AT_FLOAT2, 0);
	int vstride = vformat->GetStride();
	VertexBuffer* vbuffer = new0 VertexBuffer(5, vstride);
	VertexBufferAccessor vba(vformat, vbuffer);
	vba.Position<Float3>(0) = Float3(0.7f,  0.51f,  0.0f);
	vba.Position<Float3>(1) = Float3(1.0f,  0.51f,  0.0f);
	vba.Position<Float3>(2) = Float3(1.0f, 1.0f,  0.0f);
	vba.Position<Float3>(3) = Float3(1.0f,  1.0f, 0.0f);
	vba.Position<Float3>(4) = Float3(0.7f,  1.0f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);



	IndexBuffer*ibuffer = new0 IndexBuffer(9, sizeof(int));
	int* indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mForePoly = new0 TriMesh(vformat, vbuffer, ibuffer);
	std::string path = Environment::GetPathR("maze2.wmtf");
	Texture2DEffect* foreEffect = new0 Texture2DEffect(Shader::SF_LINEAR);
	Texture2D* texture = Texture2D::LoadWMTF(path);
	mForePoly->SetEffectInstance(foreEffect->CreateInstance(texture));

	// Make the foreground semitransparent.
	foreEffect->GetAlphaState(0, 0)->BlendEnabled = true;

	//make another one for for the player



	// A portion of the foreground is a textured screen polygon (z = 0).
	vbuffer = new0 VertexBuffer(5, vstride);
	vba.ApplyTo(vformat, vbuffer);
	outFile << "From CreateHUD(), mPlayerPos_x:"<<mPlayerPos_x<< endl;
	outFile << "HEY"<< endl;


	vba.Position<Float3>(0) = Float3(mPlayerPos_x,  mPlayerPos_y,  0.0f);
	vba.Position<Float3>(1) = Float3(mPlayerPos_x+0.01f,  mPlayerPos_y,  0.0f);
	vba.Position<Float3>(2) = Float3(mPlayerPos_x+0.01f, mPlayerPos_y+0.01f,  0.0f);
	vba.Position<Float3>(3) = Float3(mPlayerPos_x+0.01f,  mPlayerPos_y+0.01f, 0.0f);
	vba.Position<Float3>(4) = Float3(mPlayerPos_x,  mPlayerPos_y+0.01f,  0.0f);

	vba.TCoord<Float2>(0, 0) = Float2(0.0f,  0.0f);
	vba.TCoord<Float2>(0, 1) = Float2(1.0f, 0.0f);
	vba.TCoord<Float2>(0, 2) = Float2(1.0f,  1.0f);
	vba.TCoord<Float2>(0, 3) = Float2(1.0f, 1.0f);
	vba.TCoord<Float2>(0, 4) = Float2(0.0f,  1.0f);

	ibuffer = new0 IndexBuffer(9, sizeof(int));
	indices = (int*)ibuffer->GetData();
	indices[0] = 0;  indices[1] = 1;  indices[2] = 2;
	indices[3] = 0;  indices[4] = 2;  indices[5] = 3;
	indices[6] = 0;  indices[7] = 3;  indices[8] = 4;

	mForePlayer = new0 TriMesh(vformat, vbuffer, ibuffer);
	path = Environment::GetPathR("green.wmtf");
	Texture2DEffect* playerEffect = new0 Texture2DEffect(Shader::SF_LINEAR);
	texture = Texture2D::LoadWMTF(path);
	mForePlayer->SetEffectInstance(playerEffect->CreateInstance(texture));

	// Make the foreground semitransparent.
	playerEffect->GetAlphaState(0, 0)->BlendEnabled = true;

}

bool SquirrelAdven::leftKeyDown(int playerID) {
	Node * curPlayerNode = playerNodes[playerID];
	Player * curPlayer = playerList->getPlayerByID(playerID);
	APoint curTranslate = curPlayerNode->LocalTransform.GetTranslate();
	APoint posCamera = mCamera->GetPosition();

	if (playerID == 0) {

		// camera

		// rotate
		TurnLeft();

		// translate
		float dis_x = abs(curTranslate[0] - posCamera[0]);
		float dis_z = abs(curTranslate[2] - posCamera[2]);
		float distance = sqrt(dis_x * dis_x + dis_z * dis_z);

		posCamera[0] = curTranslate[0] + distance*sin(curPlayer->getDirection());
		posCamera[2] = curTranslate[2] + distance*cos(curPlayer->getDirection());
		mCamera->SetPosition(posCamera);
	}

	// player

	// rotate
	curPlayerNode->LocalTransform.SetRotate(HMatrix(AVector::UNIT_Y, rotSpeed)*curPlayerNode->LocalTransform.GetRotate());
	if (curPlayer->getDirection() + rotSpeed > 2 * PI) {
		curPlayer->setDirection(curPlayer->getDirection() - 2 * PI);
	}
	curPlayer->setDirection(curPlayer->getDirection() + rotSpeed);
		

	// pick up item
	pickUpItem(curPlayer);

	return true;
}

bool SquirrelAdven::rightKeyDown(int playerID) {
	Node * curPlayerNode = playerNodes[playerID];
	Player * curPlayer = playerList->getPlayerByID(playerID);
	APoint curTranslate = curPlayerNode->LocalTransform.GetTranslate();
	APoint posCamera = mCamera->GetPosition();

	if (playerID == 0) {

		// camera

		// rotate
		TurnRight();

		// translate
		float dis_x = abs(curTranslate[0] - posCamera[0]);
		float dis_z = abs(curTranslate[2] - posCamera[2]);
		float distance = sqrt(dis_x * dis_x + dis_z * dis_z);

		posCamera[0] = curTranslate[0] + distance*sin(curPlayer->getDirection());
		posCamera[2] = curTranslate[2] + distance*cos(curPlayer->getDirection());
		mCamera->SetPosition(posCamera);
	}

	// rotate
	curPlayerNode->LocalTransform.SetRotate(HMatrix(AVector::UNIT_Y, -rotSpeed)*curPlayerNode->LocalTransform.GetRotate());
	if (curPlayer->getDirection() - rotSpeed < -2 * PI) {
		curPlayer->setDirection(curPlayer->getDirection() + 2 * PI);
	}
	curPlayer->setDirection(curPlayer->getDirection() - rotSpeed);


	// pick up item
	pickUpItem(curPlayer);

	return true;
}

bool SquirrelAdven::upKeyDown() {
	Node * curPlayerNode = playerNodes[selfPlayerID];
	Player * curPlayer = playerList->getPlayerByID(selfPlayerID);
	APoint curTranslate = curPlayerNode->LocalTransform.GetTranslate();
	APoint posCamera = mCamera->GetPosition();

	if (AllowMotion(-1.0) == 0) {
		return true;
	}

	float t_x = -moveSpeed*sin(curPlayer->getDirection());
	float t_z = -moveSpeed*cos(curPlayer->getDirection());

	// check collision with NPC
	for (int i = 0; i < npcList->getNPCCount(); i++) {
		NPC *curNPC = npcList->getNPCByID(i);
		Float3 center_npc = curNPC->getCenterPoint();
		Float3 center_player = curPlayer->getCenterPoint();

		float dis_x = abs(center_player[0] + t_x - center_npc[0]);
		float dis_z = abs(center_player[2] + t_z - center_npc[2]);
		float distance = sqrt(dis_x * dis_x + dis_z * dis_z);

		float radius_npc = curNPC->getRadius();
		float radius_player = curPlayer->getRadius();

		if (distance <= (radius_npc + radius_player)) {
			std::cout << "collision npc: " << i << "\n";
			
			// exit
			if (curNPC->getCharacterName() == "exit") {
				if(curPlayer->numAcorns > 0 &&
				   curPlayer->numLogs > 0 &&
				   curPlayer->numRope > 0 &&
				   curPlayer->numRocks > 0) {
					gameEnd = true;
					return true;
				}
			}

			// regular NPC
			bool talkedBefore = false;
			for (int j = 0; j < talkedNPC.size(); j++) {
				if (talkedNPC[j] == i && curNPC->getCharacterName() != "exit") {
					talkedBefore = true;
					break;
				}
			}

			if (talkedBefore == false) {
				dialogMode = true;
				curTalkingNPC = curNPC;
				DialogTree * tree = curTalkingNPC->getDialogTree();
				if (tree) {
					curDialogNode = tree->getRoot();
				}
				talkedNPC.push_back(i);
			}
			return true;
		}

	}

	moveForward(selfPlayerID);
	// move forward

	UpdateHUD();

	return true;
}

bool SquirrelAdven::downKeyDown() {
	Node * curPlayerNode = playerNodes[selfPlayerID];
	Player * curPlayer = playerList->getPlayerByID(selfPlayerID);

	if (AllowMotion(1.0) == 0) {
		return true;
	}

	float t_x = moveSpeed*sin(curPlayer->getDirection());
	float t_z = moveSpeed*cos(curPlayer->getDirection());

	// check collision with NPC
	for (int i = 0; i < npcList->getNPCCount(); i++) {
		NPC *curNPC = npcList->getNPCByID(i);
		Float3 center_npc = curNPC->getCenterPoint();
		Float3 center_player = curPlayer->getCenterPoint();

		float dis_x = abs(center_player[0] + t_x - center_npc[0]);
		float dis_z = abs(center_player[2] + t_z - center_npc[2]);
		float distance = sqrt(dis_x * dis_x + dis_z * dis_z);

		float radius_npc = curNPC->getRadius();
		float radius_player = curPlayer->getRadius();

		if (distance <= (radius_npc + radius_player)) {
			std::cout << "collision npc: " << i << "\n";

			// exit
			if (curNPC->getCharacterName() == "exit") {
				if(curPlayer->numAcorns > 0 &&
				   curPlayer->numLogs > 0 &&
				   curPlayer->numRope > 0 &&
				   curPlayer->numRocks > 0) {
					gameEnd = true;
					return true;
				}
			}
			
			// regular NPC
			bool talkedBefore = false;
			for (int j = 0; j < talkedNPC.size(); j++) {
				if (talkedNPC[j] == i) {
					talkedBefore = true;
					break;
				}
			}

			if (talkedBefore == false) {
				dialogMode = true;
				curTalkingNPC = curNPC;
				DialogTree * tree = curTalkingNPC->getDialogTree();
				if (tree) {
					curDialogNode = tree->getRoot();
				}
				talkedNPC.push_back(i);
			}

			return true;
		}

	}

	moveBackward(selfPlayerID);
	// move backward

	UpdateHUD();

	return true;
}

//----------------------------------------------------------------------------
bool SquirrelAdven::AllowMotion (float sign)
{
	// Take a step forward or backward, depending on sign.  Check if objects
	// are far enough away.  If so take the step.  If not, stay where you are.

	Player * curPlayer = playerList->getPlayerByID(selfPlayerID);

	AVector D = mCamera->GetDVector();
	APoint pos = mCamera->GetPosition();

	AVector dir(sign * sin(curPlayer->getDirection()), 0,  sign * cos(curPlayer->getDirection()));

	cout << "D: " << D[0] << " " << D[1] << " " << D[2] << "\n";
	cout << "dir: " << dir[0] << " " <<dir[2] << "\n";

	mPicker.Execute(gamemap, pos, dir, 0.0f, Mathf::MAX_REAL);

	if (mPicker.Records.size() > 0)
	{
		const PickRecord& record = mPicker.GetClosestToZero();

		cout << "T: " << record.T << "\n";

		if (record.T <= (moveSpeed * 2.5))
		{
			return false;
		}
	}

	return true;
}


void SquirrelAdven::moveForward(int playerID) {
	Node * curPlayerNode = playerNodes[playerID];
	Player * curPlayer = playerList->getPlayerByID(playerID);
	APoint curTranslate = curPlayerNode->LocalTransform.GetTranslate();
	APoint posCamera = mCamera->GetPosition();

	float t_x = -moveSpeed*sin(curPlayer->getDirection());
	float t_z = -moveSpeed*cos(curPlayer->getDirection());

	// move

	if (playerID == 0) {
		// camera
		posCamera[0] += t_x;
		posCamera[2] += t_z;
		mCamera->SetPosition(posCamera);

		float ratio1 = 0.3 / (gameMap->getOriginalLengthX() * 30);
		float ratio2 = 0.49 / (gameMap->getOriginalLengthZ() * 30);

		mPlayerPos_y += ratio2*moveSpeed*sin(curPlayer->getDirection());
		mPlayerPos_x += ratio1*moveSpeed*cos(curPlayer->getDirection());
	}

	// player
	curTranslate[0] += t_x;
	curTranslate[2] += t_z;
	curPlayerNode->LocalTransform.SetTranslate(curTranslate);

	curPlayer->modifyCenterPoint(APoint (t_x, 0, t_z));

	// pick up item
	pickUpItem(curPlayer);
}

void SquirrelAdven::moveBackward(int playerID) {
	Node * curPlayerNode = playerNodes[playerID];
	Player * curPlayer = playerList->getPlayerByID(playerID);
	APoint curTranslate = curPlayerNode->LocalTransform.GetTranslate();
	APoint posCamera = mCamera->GetPosition();

	float t_x = moveSpeed*sin(curPlayer->getDirection());
	float t_z = moveSpeed*cos(curPlayer->getDirection());

	// move
	if (playerID == 0) {
		// camera
		posCamera[0] += t_x;
		posCamera[2] += t_z;
		mCamera->SetPosition(posCamera);

		float ratio1 = 0.3 / (gameMap->getOriginalLengthX() * 30);
		float ratio2 = 0.49 / (gameMap->getOriginalLengthZ() * 30);

		mPlayerPos_y -= ratio2*moveSpeed*sin(curPlayer->getDirection());
		mPlayerPos_x -= ratio1*moveSpeed*cos(curPlayer->getDirection());
	}

	// player
	curTranslate[0] += t_x;
	curTranslate[2] += t_z;
	curPlayerNode->LocalTransform.SetTranslate(curTranslate);

	curPlayer->modifyCenterPoint(APoint (t_x, 0, t_z));

	// pick up item
	pickUpItem(curPlayer);
}

void SquirrelAdven::pickUpItem(Player * curPlayer) {
	// check collision with Item
	for (int i = 0; i < itemList->getItemCount(); i++) {
		Items *curItem = itemList->getItemByID(i);
		Float3 center_item = curItem->getCenterPoint();
		Float3 center_player = curPlayer->getCenterPoint();

		float dis_x = abs(center_player[0] - center_item[0]);
		float dis_z = abs(center_player[2] - center_item[2]);
		float distance = sqrt(dis_x * dis_x + dis_z * dis_z);

		//std::cout << "distance: " << distance << "\n";

		float radius_item = curItem->getRadius();
		float radius_player = curPlayer->getRadius();

		if (distance <= (radius_item + radius_player)) {
			std::cout << "collision item: " << i << "\n";

			APoint translate_p (-1000, -1000, -1000);
			curItem->getItemMesh()->LocalTransform.SetTranslate(translate_p);
			curItem->modifyCenterPoint(translate_p);
			curPlayer->addToInventory(curItem);
		}
	}
}

void SquirrelAdven::talkWithNPC(Player * curPlayer) {
	DialogTree * tree = curTalkingNPC->getDialogTree();
	// dialog text
	std::string dialogText = tree->getCurrentDialogText(curDialogNode);

	// non-question
	if (curDialogNode->getDialogType() == 0) {
		mNPCMessage_npc = dialogText;
		std::string temp = mNPCMessage_npc;
		if (temp == "Hedgebert took all of your acorns."
			|| temp == "You did well, but Hedgebert McPricklesworth the Hedgehog stole all your acorns anyway.")
		{
			curPlayer->numAcorns = 0;
		}
		if (temp == "Norbert gave you a log!" && logGivenN == false)
		{
			curPlayer->numLogs++;
			logGivenN = true;
		}
		if (temp == "Daggett gave you a log!" && logGivenD == false)
		{
			curPlayer->numLogs++;
			logGivenD = true;
		}
		if (temp == "Batman gave you a rock!")
		{
			curPlayer->numRocks++;
		}
		if (temp == "Peanut gave you a rope!")
		{
			curPlayer->numRope++;
		}
		if (temp == "Mr. Hopkins gave you a map!")
		{
			showMap = true;
			cout << "showMap: " << showMap << "\n";
		}

		mNPCMessage_option = "";
		mNPCMessage_player = "";
	}
	// question
	else if (curDialogNode->getDialogType() == 1) {
		int index = dialogText.find("Options:");
		mNPCMessage_npc = dialogText.substr(0, index);
		mNPCMessage_option = dialogText.substr(index, dialogText.size() - index);
		mNPCMessage_player = "";
	}
	// option
	else if (curDialogNode->getDialogType() == 2) {
		// find children
		if (curDialogNode->getChildrenCount() > 0) {
			curDialogNode = tree->getNextDialogNode(curDialogNode, option);
			curPlayer->addPoints(curDialogNode->getDialogPoints());
			dialogText = tree->getCurrentDialogText(curDialogNode);

			// non-question
			if (curDialogNode->getDialogType() == 0) {
				mNPCMessage_npc = dialogText;
				std::string temp = mNPCMessage_npc;
				std::cout<<mNPCMessage_npc<<"\n";

				if (temp == "Hedgebert took all of your acorns."
					|| temp == "You did well, but Hedgebert McPricklesworth the Hedgehog stole all your acorns anyway.")
				{
					curPlayer->numAcorns = 0;
				}
				if (temp == "Norbert gave you a log!"
					|| temp == "Daggett gave you a log!")
				{
					curPlayer->numLogs++;
				}
				if (temp == "Batman gave you a rock!")
				{
					curPlayer->numRocks++;
				}
				if (temp == "Peanut gave you a rope!")
				{
					curPlayer->numRope++;
				}
				if (temp == "Mr. Hopkins gave you a map!")
				{
					showMap = true;
					cout << "showMap: " << showMap << "\n";
				}
				
				mNPCMessage_option = "";
				mNPCMessage_player = "";
			}
			// question
			else if (curDialogNode->getDialogType() == 1) {
				int index = dialogText.find("Options:");
				mNPCMessage_npc = dialogText.substr(0, index);

				mNPCMessage_option = dialogText.substr(index, dialogText.size() - index);
				mNPCMessage_player = "";
			}

		}
		// no next dialog node
		else {
			dialogMode = false;
		}
	}
}
//defining listening thread for multiplayer mode and 
#if defined (MULTIPLAYERMODE)
//multiplayer function,receives a buffer from network.receive. this is the function to parse it in

void SquirrelAdven::CheckMsg(char *recvbuf){

	//printf("Received this string from server:%s\nNow I plan to parse it into the game\n",recvbuf);
	char messageType;
	int len=strlen(recvbuf);
	char *token;
	token=strtok(recvbuf,"\n");
	//for each message in the recv

	while(token!=NULL){
		//string message
		string message(token);
		messageType=recvbuf[0];
		message=message.substr(2,len);

		//printf("messageType:%c\n",messageType);
		//cout<<"message:"<<message<<endl;

		// update actions for player 1
		int playerID = 1;


		if(messageType=='0'){
			memset(ServerMessage,0,strlen(ServerMessage));//erase server message
			message.copy(ServerMessage,message.length());//copy new msg

			//cout << ServerMessage << "\n";
		}
		else if(messageType=='2'){
			//move
			if (message == "forward") {
				moveForward(playerID);
			}
			else{ 
				moveBackward(playerID);
			}

		}
		else if(messageType=='3'){
			//rotate
			if (message == "rotateleft") {
				leftKeyDown(playerID);
			}
			else  {
				rightKeyDown(playerID);
			}

		}
		else{

		}



		token=strtok(NULL,"\n");
	}
}


#ifdef OS_WIN
//void* data
int SquirrelAdven::ThreadFunc(void* pThis) {
	return ((SquirrelAdven*)(pThis))->Process();
}
int SquirrelAdven::Process(){
	int running=1;
	char recvbuf[DEFAULT_BUFLEN];
	while(running==1){

		int iResult=network.receiveMessage(recvbuf);
		if(iResult>0){
			CheckMsg(recvbuf);
		}
	}

	// When this function returns, the thread goes away.  See MSDN for more details.
	return 0;
}
#else

void * SquirrelAdven::listen(void)
{
	int running=1;
	char recvbuf[DEFAULT_BUFLEN];
	while(running==1){

		int iResult=network.receiveMessage(recvbuf);
		if(iResult>0){
			CheckMsg(recvbuf);
		}
	}

	// When this function returns, the thread goes away.
	return 0;
}

void * SquirrelAdven::listen_helper(void *context)
{
	return ((SquirrelAdven*)context)->listen();
}

#endif
#endif